<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <script type="text/javascript">
        /**
         * 这题虽然没啥难度但值得斟酌的地方可不少，咱刷题可不能只看结果
         * 
         * 1. 我们已知JS将数组当作参数传递传的是引用，
         *    也就是说我们在函数里面的修改是会修改外部的，那还需要返回值吗，不需要对吧
         *    这里既然需要返回值说明我们不应该修改原数组，也就是说使用深拷贝，
         *    我们的深拷贝采用朴素的方法，使用JSON.parse(JSON.stringify(obj))嵌套
         *    深拷贝会经常使用，所以封装个函数也是情有可原，对吧
         * 
         * 2. sort函数的条件咱之前说过很多次，这次就省略了，
         *    但是计算总分的函数是不是值得封装一下，
         *    如果只是一个一个列举的话，很难复用对吧，所以我们可以传入需要参与计算的属性
         *    当然为了这题方便，我们完全可以给这个参数设个默认值，
         *    考虑到属性值可能字符串存的数字，顺便也转化一下
         */
      const _rank = (array) => {
        const newArray = deepCopy(array);

        // 补全代码
        newArray.sort((firstItem, secondItem) => {
          return getTotalPoints(secondItem) - getTotalPoints(firstItem);
        });
        return newArray;
      };

      /**
       * 获取学生总分
       * @param {object} item - 学生对象
       * @param {string[]} [subjects=["chinese","math","english"]]  - 课程列表
       * @returns {number} - 学生总分
       */
      const getTotalPoints = (
        item,
        subjects = ["chinese", "math", "english"]
      ) => {
        let totalPoints = 0;
        subjects.forEach((subject) => {
          totalPoints += Number(item[subject]);
        });
        return totalPoints;
      };

      /**
       * 深拷贝
       * @param {object} obj - 需要拷贝的对象
       * @returns {object} - 拷贝后的对象
       */
      const deepCopy = (obj) => {
        return JSON.parse(JSON.stringify(obj));
      };

      let students = [
        { id: "1", chinese: 90, math: 90, english: 100 },
        { id: "2", chinese: 90, math: 100, english: 80 },
        { id: "3", chinese: 100, math: 100, english: 90 },
      ];

      console.log(_rank(students));
      console.log(students); //原始数据不变
    </script>
  </body>
</html>
